package com.iking.toolkit.formatdeal.service.impl;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.esotericsoftware.minlog.Log;
import com.iking.toolkit.formatdeal.model.dto.AddWatermarkToPdfDTO;
import com.iking.toolkit.formatdeal.service.WatermarkService;
import com.iking.toolkit.model.Msg;
import com.iking.toolkit.system.model.model.DictionaryItems;
import com.iking.toolkit.util.ApiUrlUtil;
import com.iking.toolkit.util.FileFormatUtil;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

/**
 * 功能描述:水印管理
 *
 * @author: yfl
 * @date: 2025/8/4 17:50
 */
@Slf4j
@Service
public class WatermarkServiceImpl implements WatermarkService {

    @Autowired
    private ApiUrlUtil apiUrlUtil;

    /**
     * 功能描述: 添加暗水印到pdf文件上
     *
     * @param: [multipartFile, addWatermarkToPdfDTO, response]
     * @author: yfl
     * @date: 2025/8/4 18:01
     */
    @Override
    public Msg addWatermarkToPdf(MultipartFile multipartFile, AddWatermarkToPdfDTO addWatermarkToPdfDTO, HttpServletResponse response) {
        File file = null;
        try {
            String watermarkApiUrl = apiUrlUtil.getOcrApiUrl();
            if (StringUtils.isBlank(watermarkApiUrl)) {
                return Msg.fail("ocrApiUrl参数未配置!");
            }
            file = FileFormatUtil.multipartFileToFile(multipartFile);
            Map<String, Object> formMap = new HashMap<>();
            formMap.put("watermark_text", addWatermarkToPdfDTO.getWatermarkText());
            formMap.put("angle", addWatermarkToPdfDTO.getAngle());
            formMap.put("font_size", addWatermarkToPdfDTO.getFontSize());
            formMap.put("dpi", addWatermarkToPdfDTO.getDpi());
            // 发送POST请求，指定Content-Type为application/json
            byte[] pdfBytes = null;
            try (HttpResponse httpResponse = HttpRequest.post(watermarkApiUrl + "/api/add_watermark_to_pdf")
                    .form("file", file)
                    .form(formMap)
                    .header("Content-Type", "application/json")  // 关键：指定JSON格式
                    .timeout(30000)  // 增加超时时间，避免网络延迟导致失败
                    .execute()) {

                if (!httpResponse.isOk()) {
                    return Msg.fail("添加暗水印到pdf文件上失败，状态码：" + httpResponse.getStatus());
                }
                pdfBytes = httpResponse.bodyBytes();
            } catch (io.jsonwebtoken.io.IOException e) {
                return Msg.fail("请求异常：" + e.getMessage());
            }

            // 设置文件类型
            response.setContentType("application/pdf");
            // 生成文件名（带时间戳避免重复）
            String fileName = "暗水印" + System.currentTimeMillis() + ".pdf";
            // 处理中文文件名乱码
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());
            // 告诉浏览器以附件形式下载
            response.setHeader("Content-Disposition",
                    "attachment; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName);
            // 设置文件大小
            response.setContentLength(pdfBytes.length);

            // 关键改进3：将文件流写入响应体
            try (OutputStream os = response.getOutputStream()) {
                os.write(pdfBytes);
                os.flush();  // 确保所有数据写出
            }

        } catch (io.jsonwebtoken.io.IOException e) {
            return Msg.fail("文件返回失败：" + e.getMessage());
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        } catch (java.io.IOException e) {
            throw new RuntimeException(e);
        } finally {
            // 关键改进：在finally块中确保文件被删除，无论成功失败都会执行
            if (file != null && file.exists()) {
                // 尝试删除文件
                boolean deleted = file.delete();
                if (!deleted) {
                    // 若删除失败，记录警告日志
                    log.warn("临时文件删除失败，路径：{}", file.getAbsolutePath());
                    // 作为备选方案，设置延迟删除（防止当前有进程占用文件）
                    file.deleteOnExit();
                }
            }
        }
        // 无需返回Msg对象，文件流已通过response写出
        return null;
    }

    /**
     * 功能描述: 添加暗水印到pdf文件url上
     *
     * @param: [addWatermarkToPdfDTO, response]
     * @author: yfl
     * @date: 2025/8/5 14:08
     */
    @Override
    public Msg addWatermarkToUrl(AddWatermarkToPdfDTO addWatermarkToPdfDTO, HttpServletResponse response) {
        try {
            String watermarkApiUrl = apiUrlUtil.getOcrApiUrl();
            if (StringUtils.isBlank(watermarkApiUrl)) {
                return Msg.fail("ocrApiUrl参数未配置!");
            }
            Map<String, Object> formMap = new HashMap<>();
            formMap.put("url", addWatermarkToPdfDTO.getUrl());
            formMap.put("watermark_text", addWatermarkToPdfDTO.getWatermarkText());
            formMap.put("angle", addWatermarkToPdfDTO.getAngle());
            formMap.put("font_size", addWatermarkToPdfDTO.getFontSize());
            formMap.put("dpi", addWatermarkToPdfDTO.getDpi());
            // 发送POST请求，指定Content-Type为application/json
            byte[] pdfBytes = null;
            try (HttpResponse httpResponse = HttpRequest.post(watermarkApiUrl + "/api/add_watermark_to_url")
                    .form(formMap)
                    .timeout(30000)  // 增加超时时间，避免网络延迟导致失败
                    .execute()) {

                if (!httpResponse.isOk()) {
                    return Msg.fail("添加暗水印到pdf文件url上失败，状态码：" + httpResponse.getStatus());
                }
                pdfBytes = httpResponse.bodyBytes();
            } catch (io.jsonwebtoken.io.IOException e) {
                return Msg.fail("请求异常：" + e.getMessage());
            }

            // 设置文件类型
            response.setContentType("application/pdf");
            // 生成文件名（带时间戳避免重复）
            String fileName = "暗水印" + System.currentTimeMillis() + ".pdf";
            // 处理中文文件名乱码
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());
            // 告诉浏览器以附件形式下载
            response.setHeader("Content-Disposition",
                    "attachment; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName);
            // 设置文件大小
            response.setContentLength(pdfBytes.length);

            // 关键改进3：将文件流写入响应体
            try (OutputStream os = response.getOutputStream()) {
                os.write(pdfBytes);
                os.flush();  // 确保所有数据写出
            }

        } catch (io.jsonwebtoken.io.IOException e) {
            return Msg.fail("文件返回失败：" + e.getMessage());
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        } catch (java.io.IOException e) {
            throw new RuntimeException(e);
        }
        // 无需返回Msg对象，文件流已通过response写出
        return null;
    }

    /**
     * 功能描述: 上传pdf文件,解析暗水印,返回暗水印图片
     *
     * @param: [multipartFile, response]
     * @author: yfl
     * @date: 2025/8/5 15:18
     */
    @Override
    public Msg extractWatermarkFromPdf(MultipartFile multipartFile, HttpServletResponse response) {
        File file = null;
        try {
            String watermarkApiUrl = apiUrlUtil.getOcrApiUrl();
            if (StringUtils.isBlank(watermarkApiUrl)) {
                return Msg.fail("ocrApiUrl参数未配置!");
            }
            file = FileFormatUtil.multipartFileToFile(multipartFile);
            // 发送POST请求，指定Content-Type为application/json
            byte[] pdfBytes = null;
            try (HttpResponse httpResponse = HttpRequest.post(watermarkApiUrl + "/api/extract_watermark_from_pdf")
                    .form("file", file)
                    .timeout(30000)  // 增加超时时间，避免网络延迟导致失败
                    .execute()) {
                if (!httpResponse.isOk()) {
                    return Msg.fail("解析pdf文件暗水印失败，状态码：" + httpResponse.getStatus());
                }
                pdfBytes = httpResponse.bodyBytes();
            } catch (io.jsonwebtoken.io.IOException e) {
                return Msg.fail("请求异常：" + e.getMessage());
            }

            // 设置文件类型
            response.setContentType("application/png");
            // 生成文件名（带时间戳避免重复）
            String fileName = "暗水印" + System.currentTimeMillis() + ".png";
            // 处理中文文件名乱码
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());
            // 告诉浏览器以附件形式下载
            response.setHeader("Content-Disposition",
                    "attachment; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName);
            // 设置文件大小
            response.setContentLength(pdfBytes.length);

            // 关键改进3：将文件流写入响应体
            try (OutputStream os = response.getOutputStream()) {
                os.write(pdfBytes);
                os.flush();  // 确保所有数据写出
            }

        } catch (io.jsonwebtoken.io.IOException e) {
            return Msg.fail("文件返回失败：" + e.getMessage());
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        } catch (java.io.IOException e) {
            throw new RuntimeException(e);
        } finally {
            // 关键改进：在finally块中确保文件被删除，无论成功失败都会执行
            if (file != null && file.exists()) {
                // 尝试删除文件
                boolean deleted = file.delete();
                if (!deleted) {
                    // 若删除失败，记录警告日志
                    log.warn("临时文件删除失败，路径：{}", file.getAbsolutePath());
                    // 作为备选方案，设置延迟删除（防止当前有进程占用文件）
                    file.deleteOnExit();
                }
            }
        }
        // 无需返回Msg对象，文件流已通过response写出
        return null;
    }

    /**
     * 功能描述: 上传图片,解析暗水印,返回暗水印图片
     *
     * @param: [multipartFile, response]
     * @author: yfl
     * @date: 2025/8/5 15:22
     */
    @Override
    public Msg extractWatermarkFromImage(MultipartFile multipartFile, HttpServletResponse response) {
        File file = null;
        try {
            String watermarkApiUrl = apiUrlUtil.getOcrApiUrl();
            if (StringUtils.isBlank(watermarkApiUrl)) {
                return Msg.fail("ocrApiUrl参数未配置!");
            }
            file = FileFormatUtil.multipartFileToFile(multipartFile);
            // 发送POST请求，指定Content-Type为application/json
            byte[] pdfBytes = null;
            try (HttpResponse httpResponse = HttpRequest.post(watermarkApiUrl + "/api/extract_watermark_from_image")
                    .form("file", file)
                    .timeout(30000)  // 增加超时时间，避免网络延迟导致失败
                    .execute()) {
                if (!httpResponse.isOk()) {
                    return Msg.fail("解析图片中暗水印失败，状态码：" + httpResponse.getStatus());
                }
                pdfBytes = httpResponse.bodyBytes();
            } catch (io.jsonwebtoken.io.IOException e) {
                return Msg.fail("请求异常：" + e.getMessage());
            }

            // 设置文件类型
            response.setContentType("application/png");
            // 生成文件名（带时间戳避免重复）
            String fileName = "暗水印" + System.currentTimeMillis() + ".png";
            // 处理中文文件名乱码
            String encodedFileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());
            // 告诉浏览器以附件形式下载
            response.setHeader("Content-Disposition",
                    "attachment; filename=\"" + encodedFileName + "\"; filename*=UTF-8''" + encodedFileName);
            // 设置文件大小
            response.setContentLength(pdfBytes.length);

            // 关键改进3：将文件流写入响应体
            try (OutputStream os = response.getOutputStream()) {
                os.write(pdfBytes);
                os.flush();  // 确保所有数据写出
            }

        } catch (io.jsonwebtoken.io.IOException e) {
            return Msg.fail("文件返回失败：" + e.getMessage());
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        } catch (java.io.IOException e) {
            throw new RuntimeException(e);
        } finally {
            // 关键改进：在finally块中确保文件被删除，无论成功失败都会执行
            if (file != null && file.exists()) {
                // 尝试删除文件
                boolean deleted = file.delete();
                if (!deleted) {
                    // 若删除失败，记录警告日志
                    log.warn("临时文件删除失败，路径：{}", file.getAbsolutePath());
                    // 作为备选方案，设置延迟删除（防止当前有进程占用文件）
                    file.deleteOnExit();
                }
            }
        }
        // 无需返回Msg对象，文件流已通过response写出
        return null;
    }

}
